import { Editor, EditorEvents } from '@tiptap/core'

import { AiEditorApp, ChatMessage, createAvatar } from './AiApp'
import { AppMessageActionMenu, AppResponseActionMenu } from './AiAppAction'
import { Icons } from './Icons'

import { AiModelManager } from '../../ai/AiModelManager'
import { defineCustomElement } from '../../commons/defineCustomElement'
import { AiEditorOptions } from '../../core/AiEditor'
import { mdToHtml } from '../../util/mdUtil'

export class ChatApp extends HTMLElement implements AiEditorApp {
  messages: ChatMessage[] = []
  appMessagesDiv: HTMLDivElement
  messageTextarea: HTMLTextAreaElement
  imageButton: HTMLButtonElement
  modelSelect: HTMLSelectElement

  event!: EditorEvents['create']
  editor!: Editor;
  options!: AiEditorOptions

  constructor() {
    super()
    const modelSelectDiv = document.createElement('div')
    modelSelectDiv.classList.add('aie-container-app-models')

    const modelSelectText = document.createElement('div')
    modelSelectText.innerText = "模型："
    modelSelectDiv.appendChild(modelSelectText)

    this.modelSelect = document.createElement('select')
    this.modelSelect.classList.add('aie-model-select')
    modelSelectDiv.appendChild(this.modelSelect)

    this.appendChild(modelSelectDiv)

    this.appMessagesDiv = document.createElement('div')
    this.appMessagesDiv.classList.add('aie-container-app-messages')
    this.appendChild(this.appMessagesDiv)

    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type === 'childList' || mutation.type === 'characterData') {
          this.appMessagesDiv.scrollTop = this.appMessagesDiv.scrollHeight
        }
      })
    })
    // 配置MutationObserver
    const config = { childList: true, characterData: true }

    // 开始监听div的变化
    observer.observe(this.appMessagesDiv, config)

    const divAppInput = document.createElement('div')
    divAppInput.classList.add('aie-container-app-input')

    const divMessageContainer = document.createElement('div')
    divMessageContainer.classList.add('aie-message-container')

    this.messageTextarea = document.createElement('textarea')
    this.messageTextarea.classList.add('aie-message-textarea')
    this.messageTextarea.rows = 1
    this.messageTextarea.placeholder = '请输入内容... Shift+Enter换行；Enter发送'

    this.messageTextarea.addEventListener('keydown', (event) => {
      this.handleKeyDown(event)
    })
    this.messageTextarea.addEventListener('input', () => {
      this.messageTextarea.style.height = 'auto'
      this.messageTextarea.style.height = this.messageTextarea.scrollHeight + 'px'
    })
    divMessageContainer.appendChild(this.messageTextarea)

    this.imageButton = document.createElement('button')
    this.imageButton.classList.add('aie-image-button')
    this.imageButton.innerHTML = Icons.SendIcon
    this.imageButton.addEventListener('click', () => {
      this.sendMessage()
    })
    divMessageContainer.appendChild(this.imageButton)

    divAppInput.appendChild(divMessageContainer)

    this.appendChild(divAppInput)
  }

  handleKeyDown(event: KeyboardEvent) {
    // 检查是否按下了 Shift 和 Enter 键
    if (event.shiftKey && event.key === 'Enter') {
      // 如果是 Shift + Enter，允许默认行为（通常是换行）
      return
    }
    // 检查是否按下了 Enter 键
    if (event.key === 'Enter') {
      // 阻止默认的换行行为
      event.preventDefault()
      // 处理发送消息的逻辑
      this.sendMessage()
    }
  }

  sendMessage() {
    if (this.messageTextarea.value.trim() !== '') {
      const userMessage: ChatMessage = {
        id: Date.now(),
        role: 'user',
        content: this.messageTextarea.value
      }
      this.messages.push(userMessage)

      const userMessageDiv = document.createElement('div')
      userMessageDiv.classList.add('message')
      userMessageDiv.classList.add('message-sent')

      const userActionDown = document.createElement(
        'aie-app-message-action'
      ) as AppMessageActionMenu
      userActionDown.classList.add('hidden-content')
      userActionDown.onCreate(this.event, this.options)

      const userBubbleDiv = document.createElement('div')
      userBubbleDiv.classList.add('markdown-body')
      userBubbleDiv.classList.add('bubble')
      userBubbleDiv.classList.add('bubble-sent')
      userBubbleDiv.innerHTML = mdToHtml(this.messageTextarea.value)
      userBubbleDiv.setAttribute("InnerContent", this.messageTextarea.value)
      userActionDown.bindSourceElement(userBubbleDiv, this.messageTextarea)

      const userAvatarDiv = createAvatar(Icons.UserAvatar)
      userAvatarDiv.classList.add('user-avatar')

      userMessageDiv.appendChild(userActionDown)
      userMessageDiv.appendChild(userBubbleDiv)
      userMessageDiv.appendChild(userAvatarDiv)

      this.appMessagesDiv.appendChild(userMessageDiv)

      this.messageTextarea.value = ''
      this.messageTextarea.style.height = 'auto'
      this.messageTextarea.style.height = this.messageTextarea.scrollHeight + 'px'
      this.messageTextarea.focus()

      this.receiveResponse(userMessage.content!)
    }
  }

  receiveResponse(content: string) {
    const parent = this.appMessagesDiv

    const botResponseDiv = document.createElement('div')
    botResponseDiv.classList.add('message')
    botResponseDiv.classList.add('message-received')

    const botAvatarDiv = createAvatar(Icons.BotAvatar)
    botAvatarDiv.classList.add('bot-avatar')

    const botBubbleDiv = document.createElement('div')
    botBubbleDiv.classList.add('markdown-body')
    botBubbleDiv.classList.add('bubble')
    botBubbleDiv.classList.add('bubble-received')

    const botActionDown = document.createElement('aie-app-response-action') as AppResponseActionMenu
    botActionDown.classList.add('hidden-content')
    botActionDown.onCreate(this.event, this.options)
    botActionDown.bindSourceElement(botBubbleDiv)

    botResponseDiv.appendChild(botAvatarDiv)
    botResponseDiv.appendChild(botBubbleDiv)
    botResponseDiv.appendChild(botActionDown)

    parent.appendChild(botResponseDiv)

    const aiModel = AiModelManager.get(this.modelSelect.value)
    const textQueue: string[] = []
    if (aiModel) {
      aiModel.chat(content, '', {
        onStart() {
          parent.scrollTop = parent.scrollHeight
        },
        onStop() {
          botBubbleDiv.setAttribute("InnerContent", textQueue.join(''))
          parent.scrollTop = parent.scrollHeight
        },
        onMessage(message) {
          textQueue.push(message.content)
          botBubbleDiv.innerHTML = mdToHtml(textQueue.join(''))
          parent.scrollTop = parent.scrollHeight
        }
      })
    }
  }

  onCreate(event: EditorEvents['create'], options: AiEditorOptions): void {
    this.event = event
    this.editor = event.editor
    this.options = options

    if (this.options.ai && this.options.ai.models) {
      for (let model of Object.keys(this.options.ai.models)) {
        const option = document.createElement('option');
        option.textContent = model;
        this.modelSelect.appendChild(option);
      }
    }
  }

  onTransaction(event: EditorEvents['transaction']): void { }
}

defineCustomElement('aie-chat-app', ChatApp)
